/*
 * Copyright (C) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.bruce.pickerview.popwindow;

import com.bruce.pickerview.LoopView;
import com.bruce.pickerview.ResourceTable;
import com.bruce.pickerview.utils.PickUtils;
import ohos.agp.animation.Animator;
import ohos.agp.animation.AnimatorProperty;
import ohos.agp.components.*;
import ohos.agp.utils.Color;
import ohos.agp.window.dialog.PopupDialog;
import ohos.app.Context;
import ohos.hiviewdfx.HiLog;
import ohos.hiviewdfx.HiLogLabel;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.Locale;

/**
 * 日期滚轮工具类
 */
public class DatePickerPopWin extends PopupDialog implements Component.ClickedListener {
    private static final HiLogLabel TAG = new HiLogLabel(HiLog.LOG_APP, 0x000110, "DatePickerPopWin----");
    private static final int DEFAULT_MIN_YEAR = 1900;
    private Component rootView;
    private Component pickView;
    private Component outerView;
    private Button cancel;
    private Button confirm;
    private LoopView pickYear;
    private LoopView pickMonth;
    private LoopView pickDay;

    private int minYear;
    private int maxYear;
    private int yearPos = 0;
    private int monthPos = 0;
    private int dayPos = 0;
    private String textCancel;
    private String textConfirm;
    private int colorCancel;
    private int colorConfirm;
    private int btnTextsize;
    private OnDatePickedListener mListener;

    private final List<String> yearList = new ArrayList<>();
    private final List<String> monthList = new ArrayList<>();
    private final List<String> dayList = new ArrayList<>();

    private AnimatorProperty pickAnim;

    private DatePickerPopWin(Context context, Component contentComponent, Builder builder) {
        super(context, contentComponent);
        init(context, builder);
    }

    private DatePickerPopWin(Context context, Component contentComponent, int width, int height, Builder builder) {
        super(context, contentComponent, width, height);
        init(context, builder);
    }

    private void init(Context context, Builder builder) {
        this.minYear = builder.minYear;
        this.maxYear = builder.maxYear;
        this.textCancel = builder.textCancel;
        this.textConfirm = builder.textConfirm;
        this.mListener = builder.listener;
        this.colorCancel = builder.colorCancel;
        this.colorConfirm = builder.colorConfirm;
        this.btnTextsize = builder.btnTextSize;
        setSelectedDate(builder.dateChose);
        initView(context);
    }

    private void initView(Context context) {
        rootView = LayoutScatter.getInstance(context).parse(ResourceTable.Layout_layout_date_picker, null, true);
        pickView = rootView.findComponentById(ResourceTable.Id_container_picker);
        outerView = rootView.findComponentById(ResourceTable.Id_cpt_outer);
        cancel = (Button) rootView.findComponentById(ResourceTable.Id_btn_cancel);
        confirm = (Button) rootView.findComponentById(ResourceTable.Id_btn_confirm);
        pickYear = (LoopView) rootView.findComponentById(ResourceTable.Id_picker_year);
        pickMonth = (LoopView) rootView.findComponentById(ResourceTable.Id_picker_month);
        pickDay = (LoopView) rootView.findComponentById(ResourceTable.Id_picker_day);
        cancel.setTextColor(new Color(colorCancel));
        confirm.setTextColor(new Color(colorConfirm));
        cancel.setTextSize(AttrHelper.fp2px(btnTextsize, context));
        confirm.setTextSize(AttrHelper.fp2px(btnTextsize, context));
        outerView.setClickedListener(this);
        cancel.setClickedListener(this);
        confirm.setClickedListener(this);
        pickYear.setLoopListener(item -> {
            yearPos = item;
            initDayPickerView();
        });
        pickMonth.setLoopListener(item -> {
            monthPos = item;
            initDayPickerView();
        });
        pickDay.setLoopListener(item -> dayPos = item);
        initPickerViews(); // init year and month loop view
        initDayPickerView(); //init day loop view
        if (textCancel != null && !"".equals(textCancel)) {
            cancel.setText(textCancel);
        }
        if (textConfirm != null && !"".equals(textConfirm)) {
            confirm.setText(textConfirm);
        }
        setCustomComponent(rootView);
        setSize(ComponentContainer.LayoutConfig.MATCH_PARENT, ComponentContainer.LayoutConfig.MATCH_PARENT);
        setTransparent(true);
        setBackColor(new Color(Color.getIntColor("#33000000")));
    }

    @Override
    public void onClick(Component cpt) {
        if (cpt == outerView || cpt == cancel) {
            pickAnim(false);
        } else if (cpt == confirm) {
            if (mListener != null) {
                int year = minYear + yearPos;
                int month = monthPos + 1;
                int day = dayPos + 1;
                String sb = year +
                        "-" +
                        PickUtils.format2LenStr(month) +
                        "-" +
                        PickUtils.format2LenStr(day);
                mListener.onDatePickCompleted(year, month, day, sb);
            }
            pickAnim(false);
        } else {
            HiLog.info(TAG, "");
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (pickAnim != null) {
            pickAnim = null;
        }
    }

    private void initPickerViews() {
        int yearCount = maxYear - minYear;
        for (int i = 0; i < yearCount; i++) {
            yearList.add(PickUtils.format2LenStr(minYear + i));
        }
        for (int j = 0; j < 12; j++) {
            monthList.add(PickUtils.format2LenStr(j + 1));
        }
        pickYear.setDataList(yearList);
        pickYear.setInitPosition(yearPos);
        pickMonth.setDataList(monthList);
        pickMonth.setInitPosition(monthPos);
    }

    private void initDayPickerView() {
        int dayMaxInMonth;
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.YEAR, minYear + yearPos);
        calendar.set(Calendar.MONTH, monthPos);
        dayMaxInMonth = calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
        for (int i = 0; i < dayMaxInMonth; i++) {
            dayList.add(PickUtils.format2LenStr(i + 1));
        }
        pickDay.setDataList(dayList);
        pickDay.setInitPosition(dayPos);
    }

    private void setSelectedDate(String dateStr) {
        if (dateStr != null && !"".equals(dateStr)) {
            long milliseconds = PickUtils.getLongFromyyyyMMdd(dateStr);
            Calendar calendar = Calendar.getInstance(Locale.CHINA);
            if (milliseconds != -1) {
                calendar.setTimeInMillis(milliseconds);
                yearPos = calendar.get(Calendar.YEAR) - minYear;
                monthPos = calendar.get(Calendar.MONTH);
                dayPos = calendar.get(Calendar.DAY_OF_MONTH) - 1;
            }
        }
    }

    private void pickAnim(boolean flag) {
        if (pickAnim == null) {
            pickAnim = pickView.createAnimatorProperty();
        }
        pickAnim.setStateChangedListener(new Animator.StateChangedListener() {
            @Override
            public void onStart(Animator animator) {
            }

            @Override
            public void onStop(Animator animator) {
                dismiss(flag);
            }

            @Override
            public void onCancel(Animator animator) {
                dismiss(flag);
            }

            @Override
            public void onEnd(Animator animator) {
                dismiss(flag);
            }

            @Override
            public void onPause(Animator animator) {
            }

            @Override
            public void onResume(Animator animator) {
            }
        });
        int rh = rootView.getHeight();
        int ph = pickView.getHeight();
        float start = flag ? rh : rh - ph;
        float stop = flag ? rh - ph : rh;
        pickAnim.moveFromY(start).moveToY(stop).setDuration(400).start();
    }

    private void dismiss(boolean flag) {
        if (!flag) {
            hide();
        }
    }

    public void showPopWin() {
        show();
        pickAnim(true);
    }

    public static class Builder {
        private final Context context;
        private final OnDatePickedListener listener;
        private int minYear = DEFAULT_MIN_YEAR;
        private int maxYear = Calendar.getInstance().get(Calendar.YEAR) + 1;
        private String textCancel = "Cancel";
        private String textConfirm = "Confirm";
        private String dateChose = PickUtils.getStrDate();
        private int colorCancel = Color.getIntColor("#999999");
        private int colorConfirm = Color.getIntColor("#303F9F");
        private int btnTextSize = 16;

        public Builder(Context context, OnDatePickedListener listener) {
            this.context = context;
            this.listener = listener;
        }

        public Builder minYear(int minYear) {
            this.minYear = minYear;
            return this;
        }

        public Builder maxYear(int maxYear) {
            this.maxYear = maxYear;
            return this;
        }

        public Builder textCancel(String textCancel) {
            this.textCancel = textCancel;
            return this;
        }

        public Builder textConfirm(String textConfirm) {
            this.textConfirm = textConfirm;
            return this;
        }

        public Builder dateChose(String dateChose) {
            this.dateChose = dateChose;
            return this;
        }

        public Builder colorCancel(int colorCancel) {
            this.colorCancel = colorCancel;
            return this;
        }

        public Builder colorConfirm(int colorConfirm) {
            this.colorConfirm = colorConfirm;
            return this;
        }

        public Builder btnTextSize(int textSize) {
            this.btnTextSize = textSize;
            return this;
        }

        public DatePickerPopWin build() {
            if (minYear > maxYear) {
                throw new IllegalArgumentException();
            }
            return new DatePickerPopWin(context, null, this);
        }

    }

    public interface OnDatePickedListener {
        /**
         * Listener when date has been checked
         *
         * @param year     year
         * @param month    month
         * @param day      day
         * @param dateDesc yyyy-MM-dd
         */
        void onDatePickCompleted(int year, int month, int day, String dateDesc);
    }

}